package org.jeecg.modules.demo.socket.until;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;


/**
 * TextWebSocketFrame类型， 表示一个文本帧
 * @author sixiaojie
 * @date 2020-03-28-13:47
 */
@Component
@ChannelHandler.Sharable
@Slf4j
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {


  /**
   * 一旦连接，第一个被执行
   * @param ctx
   * @throws Exception
   */
  @Override
  public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
    log.info("运行到WebSocketHandler的handlerAdded(ChannelHandlerContext ctx)");
    log.info("handlerAdded 被调用"+ctx.channel().id().asLongText());
    // 添加到channelGroup 通道组
    NettyConfig.getChannelGroup().add(ctx.channel());
  }

  /**
   * 读取数据
   */
  @Override
  protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
    log.info("运行到WebSocketHandler的channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg)");
    log.info("服务器收到消息：{}",msg.text());
    // 获取用户ID,关联channel
    JSONObject jsonObject = JSONUtil.parseObj(msg.text());
    String uid = jsonObject.getStr("uid");
    NettyConfig.getUserChannelMap().put(uid,ctx.channel());
    // 将用户ID作为自定义属性加入到channel中，方便随时channel中获取用户ID
    AttributeKey<String> key = AttributeKey.valueOf("userId");
    ctx.channel().attr(key).setIfAbsent(uid);
    // 回复消息
    ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器连接成功！"));
  }
  @Override
  public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
    log.info("运行到WebSocketHandler的handlerRemoved(ChannelHandlerContext ctx)");
    log.info("handlerRemoved 被调用"+ctx.channel().id().asLongText());
    // 删除通道
    NettyConfig.getChannelGroup().remove(ctx.channel());
    removeUserId(ctx);
  }
  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    log.info("运行到WebSocketHandler的exceptionCaught(ChannelHandlerContext ctx, Throwable cause)");
    log.info("异常：{}",cause.getMessage());
    // 删除通道
    NettyConfig.getChannelGroup().remove(ctx.channel());
    removeUserId(ctx);
    ctx.close();
  }
  /**
   * 删除用户与channel的对应关系
   */
  private void removeUserId(ChannelHandlerContext ctx){
    log.info("运行到WebSocketHandler的removeUserId(ChannelHandlerContext ctx)");
    AttributeKey<String> key = AttributeKey.valueOf("userId");
    String userId = ctx.channel().attr(key).get();
    NettyConfig.getUserChannelMap().remove(userId);
  }
}